package com.handpay.framework.swiper;

import android.bluetooth.BluetoothDevice;
import android.content.Context;
import android.text.TextUtils;
import android.util.Log;

import com.bbpos.wisepad.WisePadController;
import com.bbpos.wisepad.WisePadController.BatteryStatus;
import com.bbpos.wisepad.WisePadController.CheckCardMode;
import com.bbpos.wisepad.WisePadController.CheckCardResult;
import com.bbpos.wisepad.WisePadController.CurrencyCharacter;
import com.bbpos.wisepad.WisePadController.DisplayText;
import com.bbpos.wisepad.WisePadController.EmvOption;
import com.bbpos.wisepad.WisePadController.Error;
import com.bbpos.wisepad.WisePadController.PhoneEntryResult;
import com.bbpos.wisepad.WisePadController.PinEntryResult;
import com.bbpos.wisepad.WisePadController.PinEntrySource;
import com.bbpos.wisepad.WisePadController.PrintResult;
import com.bbpos.wisepad.WisePadController.StartEmvResult;
import com.bbpos.wisepad.WisePadController.TerminalSettingStatus;
import com.bbpos.wisepad.WisePadController.TransactionResult;
import com.bbpos.wisepad.WisePadController.WisePadControllerListener;
import com.handpay.framework.swiper.ic.IICSelectApplicationCallback;
import com.handpay.framework.swiper.ic.IShowSelectApplication;
import com.handpay.framework.utils.CommonUtils;
import com.handpay.zztong.hp.R;
import com.handpay.zztong.hp.ZZTApplication;
import com.handpay.zztong.hp.config.ZZTConstant;
import com.handpay.zztong.hp.log.HPLog;

import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.Hashtable;
import java.util.List;
import java.util.Locale;
import java.util.concurrent.TimeoutException;


/**
 * Bbpos M188蓝牙刷卡器封装
 * @author yliang
 *
 */
public class BbposM188 extends AbstractBbposSwiper implements WisePadControllerListener {

	protected WisePadController wisePadController;
	private static final String TAG = BbposM188.class.getSimpleName();
	private String mData;
	WisePadController.CheckCardResult mCheckCardResult;
	protected IShowSelectApplication mSelectApplication;
	private Context mContext;
	private SwipeTransData mSwipeTransData;
	protected static String apdus[] = { "8A023030", "80fa000018363232383738303231323231393330373030000000000000", };
	private volatile boolean mIsSwiperOK = true;
	private PinEntryResult pinResult = PinEntryResult.NO_PIN;
	private Boolean isSetAmount = false;

	public BbposM188(Context context, String address, IShowSelectApplication selectApplication) {
		HPLog.i(TAG, "BBposM188--------初始化：" + ZZTApplication.getInstance().bdDevice.getName());
		wisePadController = WisePadController.getInstance(context, this);
		// if(ZZTApplication.getInstance().bdDevice.getName().endsWith("LE")){
		// wisePadController.connectBTv4(ZZTApplication.getInstance().bdDevice);
		// }else {
		wisePadController.connect(ZZTApplication.getInstance().bdDevice);
		// }
		mLock = new AsynSwiperLock();
		mContext = context;
		this.mSelectApplication = selectApplication;
	}

	@Override
	public String getCSN() {
		HPLog.i(TAG, "getCSN........");
		mData = null;
		if (wisePadController != null) {
			wisePadController.getDeviceInfo();
			try {
				mLock.lock(ZZTConstant.SWIPER_TIMEOUT, AsynSwiperLock.GETCSN);
			} catch (TimeoutException te) {
				HPLog.i(TAG, "", te);
			}
			HPLog.i(TAG, "getCSN........csn = " + mData);
		}
		return mData == null ? null : mData.toUpperCase(Locale.US);
	}

	@Override
	public boolean stopOperation() {
		// if (mLock.getCurrrentCmdType() == AsynSwiperLock.NEW_SWIPE_CARD) {
		// 从文峻那里得知cancelCheckCard貌似是作用比较多
		HPLog.i(TAG, "stopOperation........");
		mCheckCardResult = null;
		if (mLock.getCurrrentCmdType() == AsynSwiperLock.NEW_INPUT_PWD) {
			HPLog.i(TAG, "stopOperation........NEW_INPUT_PWD");
			wisePadController.cancelPinEntry();
		} else if (mLock.getCurrrentCmdType() == AsynSwiperLock.OLD_INPUT_PWD) {
			HPLog.i(TAG, "stopOperation........OLD_INPUT_PWD");
			wisePadController.cancelSetAmount();
		} else {
			HPLog.i(TAG, "stopOperation........cancelCheckCard");
			wisePadController.cancelCheckCard();
		}
		mLock.unlock(AsynSwiperLock.IDLE);
		return true;
	}

	@Override
	public boolean closeDevice() {
		HPLog.i(TAG, "close.....");
		mIsSwiperOK = false;
		mSelectApplication = null;
		mContext = null;
		mSwipeTransData = null;
		mLock = null;
		if (wisePadController != null) {
			// if(ZZTApplication.getInstance().bdDevice.getName().endsWith("LE")){
			// wisePadController.stopScanBTv4();
			// }else {
			wisePadController.disconnect();
			// }
			wisePadController.stopScan();
			wisePadController = null;
		}
		return true;
	}

	private void initTransData(String factor, int timeOut) {
		// mHTData，可以在后面完全被SwipeTransData取代
		mHTData.clear();
		mSwipeTransData = new SwipeTransData();
		mSwipeTransData.mBbposICTranIndex = 0;
		mSwipeTransData.mFactor = factor;
		mSwipeTransData.mTimeout = timeOut;
	}
	

	public SwipeResult iccStartEmv() {
		int timeout = mSwipeTransData.mTimeout;
		String factor = mSwipeTransData.mFactor;
		Hashtable<String, Object> data = new Hashtable<String, Object>();
		data.put("emvOption", EmvOption.START);
		data.put("checkCardMode", CheckCardMode.SWIPE_OR_INSERT);
		data.put("randomNumber", factor);
		mData = null;
		// startEMV之前设置好金额就不会回调onRequestSetAmount
//		wisePadController.setAmount(mAmount, "0", "156", WisePadController.TransactionType.GOODS, new CurrencyCharacter[] { CurrencyCharacter.YUAN });
		wisePadController.startEmv(data);
		HPLog.i(TAG, "iccStartEmv:  读取ICC的信息");
		try {
			// 暂时用OLD_INPUT_PWD来锁住IC startEmv
			Log.e(TAG, "iccStartEmv ");
			mLock.lock(timeout * 5, AsynSwiperLock.OLD_INPUT_PWD);
		} catch (TimeoutException te) {
			HPLog.e(TAG, "", te);
		}

		if (null != mSelectApplication) {
			mSelectApplication.closeSelectICApp();
		}

		HPLog.i(TAG, "iccStartEmv:ICC的信息返回");
		String tlv = mData;
		mData = null;
		if (TextUtils.isEmpty(tlv)) {
			return new SwipeResult(SwipeStatus.SWIPE_ERROR);
		}
		Hashtable<String, String> decodeData = WisePadController.decodeTlv(tlv);

		Object[] keys = decodeData.keySet().toArray();
		String content = "";
		for (Object key : keys) {
			String value = decodeData.get(key);
			content += key + ": " + value + "\n";
			HPLog.e(TAG, "key:" + key + "   value:" + value);
		}
		HPLog.e(TAG, content);
		String PAN = decodeData.get("maskedPAN");
		if (!TextUtils.isEmpty(PAN)) {
			mHTData.put(IBusinessSwiper.BANK_PLAIN_ACCOUNT_KEY, PAN.toUpperCase(Locale.US));
		} else {
			HPLog.i(TAG, "IC card but no PAN");
		}
		String track2 = decodeData.get("encTrack2Eq");
		if (!TextUtils.isEmpty(track2)) {
			mHTData.put(IBusinessSwiper.BANK_TRACK2_KEY, BusinessSwiper.autoFillTrack2(track2.toUpperCase(Locale.US)));
		} else {
			HPLog.i(TAG, "IC card but no BANK_TRACK2");
		}
		// mAccount = decodeData.get("maskedPAN");
		// mAccount = mAccount.replace("f", "");
		String tKey = decodeData.get("encTrack2EqRandomNumber");
		if (!TextUtils.isEmpty(tKey)) {
			mHTData.put(IBusinessSwiper.BANK_DYNAMIC_KEY, tKey.toUpperCase(Locale.US));
		} else {
			HPLog.i(TAG, "IC card but no BANK_DYNAMIC");
		}
		String icNumber = decodeData.get("5f34");
		if (!TextUtils.isEmpty(icNumber)) {
			icNumber = "0" + icNumber;
			mHTData.put(IBusinessSwiper.BANK_ICNUMBER, icNumber);
		} else {
			HPLog.i(TAG, "IC card but no icNumber");
		}

		// 新版 2.0.0 添加ＩＣ卡有效期
		String plainExpireDate = decodeData.get("5F24");
		if (CommonUtils.checkExpireDate(plainExpireDate)) {
			plainExpireDate = plainExpireDate.substring(0, 4);
			HPLog.i(HPLog.FDL_TAG, "BbposM188  -- plainExpireDate:" + plainExpireDate);
			// plainExpireDate = encData(plainExpireDate,
			// ISwiperListener.KeyDataIndex, factor);
			if (!TextUtils.isEmpty(plainExpireDate)) {
				HPLog.i(HPLog.FDL_TAG, "BbposM188  ---encData--- plainExpireDate:" + plainExpireDate);
				mHTData.put(IBusinessSwiper.BANK_PLAIN_EXPIRE_DATE, plainExpireDate);
			} else {
				HPLog.e(HPLog.FDL_TAG, "enc plainExpireDate error!");
			}
			HPLog.i(HPLog.FDL_TAG, "BbposM368  -- plainExpireDate:"
					+ plainExpireDate);
			mHTData.put(IBusinessSwiper.BANK_PLAIN_EXPIRE_DATE, plainExpireDate);
		} else {
			HPLog.i(TAG, "IC card but no plainExpireDate");
		}

		// 测试！！！由于新SDK返回TLV有重复 自己组装DCDATA测试交易
		// String mdcData =
		// EmvSwipeController.viposGetIccData(_decodeData.toString());
//		String mdcData = "";
//		String[] t_key = new String[] { "5F2A", "82", "84", "95", "9A", "9C", "9F02", "9F03", "9F09", "9F10", "9F1A", "9F26", "9F27", "9F1E", "9F33", "9F34", "9F35", "9F36", "9F37", "9F41" };
//		for (int i = 0; i < t_key.length; i++) {
//			if (decodeData.containsKey(t_key[i])) {
//				String value = decodeData.get(t_key[i]).toUpperCase(Locale.US);
//				byte[] byt = new byte[2];
//				int len = value.length() / 2;
//				byt[0] = (byte) (len / 16 + 0x30);
//				byt[1] = (byte) (len % 16 + 0x30);
//				mdcData += t_key[i] + new String(byt) + value;
//			}
//		}
//		HPLog.e(TAG, "dcdata: " + mdcData);
//
//		if (!TextUtils.isEmpty(mdcData)) {
//			mHTData.put(IBusinessSwiper.BANK_DCDATA, mdcData.toUpperCase(Locale.US));
//		} else {
//			HPLog.e(TAG, "IC card but no dcData");
//			return new SwipeResult(SwipeStatus.SWIPE_ERROR);
//		}
		
		
		String mdcData = WisePadController.viposGetIccData(tlv);
		Log.e(TAG, "mdcData: "+mdcData);
		if (!TextUtils.isEmpty(mdcData)) {
			mHTData.put(IBusinessSwiper.BANK_DCDATA, mdcData.toUpperCase(Locale.US));
		} else {
			HPLog.e(TAG, "IC card but no dcData");
			return new SwipeResult(SwipeStatus.SWIPE_ERROR);
		}
		
		// M188不带密码键盘 原来M368获取密码的方式不再适应
		/*
		 * String pin = decodeData.get("99"); HPLog.e(TAG, "IC card pin :" +
		 * pin); HPLog.e(TAG, "手动加密的密码 pin :" + mHTData.get(BANK_PAN_KEY)); //
		 * 暂时写死不调用 if (TextUtils.isEmpty(pin)) { HPLog.e(TAG,
		 * "IC card pin is null:"); // return new
		 * SwipeResult(SwipeStatus.SWIPE_ERROR); Hashtable<String, Object>
		 * htData = new Hashtable<String, Object>();
		 * htData.put("pinEntryTimeout", mSwipeTransData.mTimeout);
		 * htData.put("randomNumber", mSwipeTransData.mFactor);
		 * wisePadController.startPinEntry(htData); try { mLock.lock(timeout,
		 * AsynSwiperLock.NEW_INPUT_PWD); } catch (TimeoutException te) {
		 * HPLog.i(TAG, "", te); return new
		 * SwipeResult(SwipeStatus.SWIPE_ERROR); } if (pinResult ==
		 * PinEntryResult.CANCEL) { HPLog.e(TAG,
		 * "startPinEntry IC card pin is PinEntryResult.CANCEL:"); return new
		 * SwipeResult(SwipeStatus.SWIPE_CANCEL); } if (null ==
		 * mHTData.get(BANK_PAN_KEY) || "".equals(mHTData.get(BANK_PAN_KEY))) {
		 * HPLog.e(TAG, "startPinEntry IC card pin is null:"); return new
		 * SwipeResult(SwipeStatus.SWIPE_ERROR); } } else {
		 * mHTData.put(BANK_PAN_KEY, pin); }
		 */
		return new SwipeResult(SwipeStatus.SWIPE_OK, PAN);
	}

	@Override
	public SwipeResult swipeCard(String factor, int timeout) {
		if (wisePadController == null) {
			HPLog.i(TAG, "swipeCard:wisePadController is null");
			// 当取消处理
			return new SwipeResult(SwipeStatus.SWIPE_CANCEL);
		}
		HPLog.i(TAG, "swipeCard:等待刷卡。。。。");
		Hashtable<String, Object> data = new Hashtable<String, Object>();
		String strTimeOut = "" + timeout;
		data.put("checkCardTimeout", strTimeOut);
		data.put("randomNumber", factor);
		// 每次刷卡的时候，清除所有数据
		// 2.7.2添加
		data.put("checkCardMode", CheckCardMode.SWIPE_OR_INSERT);
		initTransData(factor, timeout);
		mCheckCardResult = CheckCardResult.NONE;
		wisePadController.checkCard(data);
		try {
			mLock.lock(timeout, AsynSwiperLock.NEW_SWIPE_CARD);
		} catch (TimeoutException te) {
			HPLog.i(TAG, "", te);
			return new SwipeResult(SwipeStatus.SWIPE_TIMEOUT);
		}
		HPLog.i(TAG, "swipeCard:解锁。。。" + mCheckCardResult);
		if (CheckCardResult.MCR == mCheckCardResult) {
			// 磁条卡
			// 检查磁条刷卡所必备的数据
			if (null == mHTData.get(IBusinessSwiper.BANK_DYNAMIC_KEY)) {
				HPLog.e(TAG, "no dynamic key");
				return new SwipeResult(SwipeStatus.SWIPE_ERROR);
			}
			if (null == mHTData.get(IBusinessSwiper.BANK_TRACK2_KEY)) {
				HPLog.e(TAG, "no track2");
				return new SwipeResult(SwipeStatus.SWIPE_ERROR);
			}
			if (null == mHTData.get(IBusinessSwiper.BANK_PLAIN_ACCOUNT_KEY)) {
				HPLog.e(TAG, "no plain account");
				return new SwipeResult(SwipeStatus.SWIPE_ERROR);
			}
			SwipeResult result = new SwipeResult(SwipeStatus.SWIPE_OK, mHTData.get(IBusinessSwiper.BANK_PLAIN_ACCOUNT_KEY));
			result.mCardType = mHTData.get("cardType");
			return result;
		} else if (CheckCardResult.ICC == mCheckCardResult) {
			// IC卡
			mSwipeTransData.isIcTrans = true;
			mData = null;
			wisePadController.getEmvCardNumber();

			try {
				// 暂时用OLD_SWIPE_CARD来锁住IC的获取卡号
				mLock.lock(ZZTConstant.SWIPER_TIMEOUT, AsynSwiperLock.OLD_SWIPE_CARD);
			} catch (TimeoutException te) {
				HPLog.i(TAG, "", te);
				return new SwipeResult(SwipeStatus.SWIPE_TIMEOUT);
			}
			if (null == mCheckCardResult) {
				HPLog.i(TAG, "bbpos cancel card");
				// 当取消处理
				return new SwipeResult(SwipeStatus.SWIPE_CANCEL);
			}
			if (TextUtils.isEmpty(mData)) {
				return new SwipeResult(SwipeStatus.SWIPE_ERROR);
			}
			mHTData.put(IBusinessSwiper.BANK_PLAIN_ACCOUNT_KEY, mData);

			Log.e(HPLog.YL_TAG, "M188 swipeCard:"+mHTData.toString());
			return new SwipeResult(SwipeStatus.SWIPE_OK, mData);
			// return iccStartEmv();

		} else if (null == mCheckCardResult) {
			HPLog.i(TAG, "bbpos cancel card");
			// 当取消处理
			return new SwipeResult(SwipeStatus.SWIPE_CANCEL);
		} else {
			// 当做错误处理
			return new SwipeResult(SwipeStatus.SWIPE_ERROR);
		}
	}

	@Override
	public String encData(String data, String index, String factor) {
		HPLog.i(TAG, "data:" + data + " index:" + index + " factor:" + factor);
		mData = null;
		String time = factor.substring(0, factor.length() - 2);
		Hashtable<Integer, String[]> example = new Hashtable<Integer, String[]>();
		try {
			if (ISwiperListener.MacDataIndex.equals(index)) {
				char[] mac = data.toCharArray();
				ByteArrayOutputStream bos = new ByteArrayOutputStream();
				try {
					bos.write(new byte[] { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 });
					bos.write(String.valueOf(mac).getBytes());
					bos.write(0x80);
					while (bos.size() % 8 != 0) {
						bos.write(0x00);
					}
					byte[] dataBytes = bos.toByteArray();
					bos.close();
					for (String partMac : formatMacString(dataBytes)) {
						Hashtable<Integer, String[]> hashtable = new Hashtable<Integer, String[]>(1);
						hashtable.put(SINGLE_ENC_MAC_KEY, new String[] { "15", time, partMac });
						mData = null;
						wisePadController.viposBatchExchangeApdu(hashtable);
						mLock.lock(ZZTConstant.SWIPER_TIMEOUT, AsynSwiperLock.CACL_MAC);
						HPLog.i(TAG, partMac + " macResult: " + mData);
						if (null != mData && mData.endsWith("9000")) {
							// 成功。去掉9000。中间返回是9000，mData就是“”，最后的话，mData就是算出来的mac
							mData = mData.substring(0, mData.length() - 4).toUpperCase();
						} else {
							// 失败了。设置mac加密失败。并退出循环
							mData = null;
							break;
						}
					}
				} catch (IOException ioe) {
					HPLog.e(TAG, "", ioe);
				}
			} else if (ISwiperListener.KeyDataIndex.equals(index)) {
				String cmd = formatDataAdpu(data);
				HPLog.i(TAG, "13 cmd:" + cmd);
				example.put(SINGLE_ENC_DATA_KEY, new String[] { "13", time, cmd });
				wisePadController.viposBatchExchangeApdu(example);
				mLock.lock(ZZTConstant.SWIPER_TIMEOUT, AsynSwiperLock.CACL_DATA);
			} else if (PIN_INDEX.equals(index)) {
				example.put(SINGLE_ENC_DATA_KEY, new String[] { "14", time, "80fa00000806" + data + "ffffffff" });
				wisePadController.viposBatchExchangeApdu(example);
				mLock.lock(ZZTConstant.SWIPER_TIMEOUT, AsynSwiperLock.CACL_DATA);
			}
		} catch (TimeoutException te) {
			HPLog.i(TAG, "", te);
		}
		return mData;
	}

	@Override
	public boolean isSwiperReady() {
		return mIsSwiperOK;
	}

	@Override
	public SwiperModel getSwiperModel() {
		return SwiperModel.M188_BLUETOOTH;
	}

	@Override
	// public void onWaitingForCard() {
	// 2.7.2新增修改接口
	public void onWaitingForCard(CheckCardMode arg0) {
		HPLog.i(TAG, "onWaitingForCard:");
	}

	@Override
	public void onReturnCheckCardResult(CheckCardResult checkCardResult, Hashtable<String, String> decodeData) {
		HPLog.i(TAG, "onReturnCheckCardResult:" + checkCardResult);
		mCheckCardResult = checkCardResult;
		if (checkCardResult == CheckCardResult.MCR) {
			String formatID = decodeData.get("formatID");
			String maskedPAN = decodeData.get("maskedPAN");
			String PAN = decodeData.get("PAN");
			String plainExpireDate = decodeData.get("expiryDate");
			String cardHolderName = decodeData.get("cardholderName");
			String ksn = decodeData.get("ksn");
			String serviceCode = decodeData.get("serviceCode");
			String track1Length = decodeData.get("track1Length");
			String track2Length = decodeData.get("track2Length");
			String track3Length = decodeData.get("track3Length");
			String encTracks = decodeData.get("encTracks");
			String encTrack1 = decodeData.get("encTrack1");
			String encTrack2 = decodeData.get("encTrack2");
			String encTrack3 = decodeData.get("encTrack3");
			String track1Status = decodeData.get("track1Status");
			String track2Status = decodeData.get("track2Status");
			String track3Status = decodeData.get("track3Status");
			String partialTrack = decodeData.get("partialTrack");
			String productType = decodeData.get("productType");
			String finalMessage = decodeData.get("finalMessage");
			String dynamicKeyData = decodeData.get("randomNumber");
			String encWorkingKey = decodeData.get("encWorkingKey");
			//新版 2.0.0   添加ＩＣ卡有效期
			if (CommonUtils.checkExpireDate(plainExpireDate)) {
				plainExpireDate = plainExpireDate.substring(0, 4);
				HPLog.i(HPLog.FDL_TAG, "BbposM368  -- plainExpireDate:"+plainExpireDate);
				mHTData.put(IBusinessSwiper.BANK_PLAIN_EXPIRE_DATE, plainExpireDate);
			} else {
				HPLog.i(TAG, " BbPosSwiper IC card but no plainExpireDate");
			}
			// 随机数
			mHTData.put(IBusinessSwiper.BANK_DYNAMIC_KEY, dynamicKeyData.toUpperCase(Locale.US));
			// 2磁道
			mHTData.put(IBusinessSwiper.BANK_TRACK2_KEY, BusinessSwiper.autoFillTrack2(encTrack2.toUpperCase(Locale.US)));
			// 明文卡号
			mHTData.put(IBusinessSwiper.BANK_PLAIN_ACCOUNT_KEY, PAN);
			if(serviceCode!=null&&serviceCode.length()>0){
				// 服务码
				String cardType = serviceCode.substring(0, 1);
				if (!TextUtils.isEmpty(cardType)) {
					mHTData.put("cardType", cardType);
					mHTData.put("serviceCode", serviceCode);
				}
			}
			if (TextUtils.isEmpty(PAN) || TextUtils.isEmpty(dynamicKeyData) || TextUtils.isEmpty(encTrack2)) {
				HPLog.e(TAG, "PAN or dynamicKeyData or encTrack2 empty! notify re-swipe");
				mCheckCardResult = CheckCardResult.NONE;
			}
			/*
			 * if (serviceCode.endsWith("0") || serviceCode.endsWith("6")) {
			 * Hashtable<String, Object> data = new Hashtable<String, Object>();
			 * data.put("pinEntryTimeout", mSwipeTransData.mTimeout);
			 * data.put("randomNumber", mSwipeTransData.mFactor);
			 * wisePadController.startPinEntry(data);
			 * HPLog.e(TAG,"startPinEntry--"); }else{
			 * mLock.unlock(AsynSwiperLock.NEW_SWIPE_CARD);
			 * HPLog.e(TAG,"serviceCode.endsWith error--"); }
			 */

		}
		mLock.unlock(AsynSwiperLock.NEW_SWIPE_CARD);

	}

	@Override
	public void onReturnCancelCheckCardResult(boolean b) {
		HPLog.i(TAG, "onReturnCancelCheckCardResult:" + b);
		mCheckCardResult = null;
		mLock.unlock(AsynSwiperLock.IDLE);
	}

	@Override
	public void onReturnStartEmvResult(StartEmvResult startEmvResult, String s) {
		HPLog.i(TAG, "onReturnStartEmvResult:" + startEmvResult + " " + s);
	}

	@Override
	public void onReturnDeviceInfo(Hashtable<String, String> deviceInfoData) {
		HPLog.i(TAG, "onReturnDeviceInfo:"+deviceInfoData);
		String isSupportedTrack1 = deviceInfoData.get("isSupportedTrack1");
		String isSupportedTrack2 = deviceInfoData.get("isSupportedTrack2");
		String isSupportedTrack3 = deviceInfoData.get("isSupportedTrack3");
		String bootloaderVersion = deviceInfoData.get("bootloaderVersion");
		String firmwareVersion = deviceInfoData.get("firmwareVersion");
		String isUsbConnected = deviceInfoData.get("isUsbConnected");
		String isCharging = deviceInfoData.get("isCharging");
		String batteryLevel = deviceInfoData.get("batteryLevel");
		String batteryPercentage = deviceInfoData.get("batteryPercentage");
		String hardwareVersion = deviceInfoData.get("hardwareVersion");
		String productId = deviceInfoData.get("productId");
		String pinKsn = deviceInfoData.get("pinKsn");
		String emvKsn = deviceInfoData.get("emvKsn");
		String trackKsn = deviceInfoData.get("trackKsn");
		String csn = deviceInfoData.get("csn");
		String vendorID = deviceInfoData.get("vendorID");
		String terminalSettingVersion = deviceInfoData.get("terminalSettingVersion");
		String deviceSettingVersion = deviceInfoData.get("deviceSettingVersion");
		String formatID = deviceInfoData.get("formatID");

		mData = csn;
		HPLog.i(TAG, "onReturnDeviceInfo csn:" + mData);
		
		mLock.unlock(AsynSwiperLock.GETCSN);
	}

	@Override
	public void onReturnTransactionResult(TransactionResult transactionResult) {
		HPLog.i(TAG, "onReturnTransactionResult: __1" + transactionResult);
	}

	@Override
	public void onReturnTransactionResult(TransactionResult transactionResult, Hashtable<String, String> stringStringHashtable) {
		HPLog.i(TAG, "onReturnTransactionResult: __2" + transactionResult);
		if (TransactionResult.APPROVED == transactionResult) {

		} else {
			// swipe card failed
			// ！！！不管emv结果。我们只要拿到dcData可以做交易，就当成功了！！！
			// mData = null;
		}
		mLock.unlock(AsynSwiperLock.OLD_INPUT_PWD);

	}

	@Override
	public void onReturnBatchData(String s) {
		HPLog.i(TAG, "onReturnBatchData:" + s);
	}

	@Override
	public void onReturnTransactionLog(String s) {
		HPLog.i(TAG, "onReturnTransactionLog:" + s);
	}

	@Override
	public void onReturnReversalData(String s) {
		HPLog.i(TAG, "onReturnReversalData:" + s);
	}

	@Override
	public void onReturnViposExchangeApduResult(String s) {
		HPLog.i(TAG, "onReturnViposExchangeApduResult:" + s);
		++mSwipeTransData.mBbposICTranIndex;
		if (mSwipeTransData.mBbposICTranIndex < apdus.length) {
			wisePadController.viposExchangeApdu(apdus[mSwipeTransData.mBbposICTranIndex]);
		} else {
			wisePadController.sendOnlineProcessResult("8A023030");
		}
	}

	@Override
	public void onReturnViposBatchExchangeApduResult(Hashtable<Integer, String> data) {
		HPLog.i(TAG, "onReturnViposBatchExchangeApduResult:");
		// 单独加密数据的返回结果
		if (null != data.get(SINGLE_ENC_DATA_KEY)) {
			HPLog.i(TAG, "enc data result:" + data.get(SINGLE_ENC_DATA_KEY));
			mData = data.get(SINGLE_ENC_DATA_KEY).substring(0, data.get(SINGLE_ENC_DATA_KEY).length() - 4).toUpperCase(Locale.US);
			mLock.unlock(AsynSwiperLock.CACL_DATA);
		} else if (null != data.get(SINGLE_ENC_MAC_KEY)) {
			// 单独做mac的数据返回
			HPLog.i(TAG, "onBatchApduResponseReceived--------------" + data.get(SINGLE_ENC_MAC_KEY));
			mData = data.get(SINGLE_ENC_MAC_KEY);
			mLock.unlock(AsynSwiperLock.CACL_MAC);
		} else {

		}
	}

	@Override
	public void onReturnEmvCardDataResult(boolean b, String s) {
		HPLog.i(TAG, "onReturnEmvCardDataResult:" + b + " " + s);
	}

	@Override
	public void onReturnEmvCardNumber(String s) {
		HPLog.i(TAG, "onReturnEmvCardNumber:" + s);
		mData = s;
		mLock.unlock(AsynSwiperLock.OLD_SWIPE_CARD);
	}

	/*
	 * @Override public void onReturnAutoConfigProgress(double v) { HPLog.i(TAG,
	 * "onReturnReadTerminalSettingResult:" + v); }
	 * 
	 * @Override public void onReturnAutoConfigResult(boolean b, String s) {
	 * HPLog.i(TAG, "onReturnAutoConfigResult:" + b + " " + s); }
	 * 
	 * @Override public void onReturnSetConfigResult(boolean b) { HPLog.i(TAG,
	 * "onReturnSetConfigResult:" + b); }
	 */
	private static int findIndex(ArrayList<String> strings, String cardType) {
		int index;
		// 查找出第一的位置
		for (index = 0; index < strings.size(); index++) {
			if (cardType.equals(strings.get(index))) {
				break;
			}
		}
		return index;
	}

	@Override
	public void onRequestSelectApplication(final ArrayList<String> strings) {
		HPLog.i(TAG, "onRequestSelectApplication:");
		String applicationType = mSwipeTransData.mICSelectedApplication;
		if (!TextUtils.isEmpty(applicationType)) {
			// 一次交易中，如果用户已经选择了卡类型，直接选择
			int index = strings.indexOf(applicationType);
			HPLog.i(TAG, "user already select " + applicationType + " and index is " + index);
			if (-1 != index) {
				wisePadController.selectApplication(index);
			} else {
				wisePadController.cancelSelectApplication();
				HPLog.e(TAG, "error!");
			}
			return;
		}
		/**
		 * list 和 arrayList对应。
		 */
		final ArrayList<String> list = new ArrayList<String>(2);
		ArrayList<String> listName = new ArrayList<String>(2);
		for (int i = 0; i < strings.size(); i++) {
			String cardType = strings.get(i);
			// 超级转账的限制，放到具体业务里，不要放在刷卡器里
			if (cardType.contains("CREDIT")/*
											 * && mSwiperMode !=
											 * SwiperMode.SUPER_TRANS
											 */) {
				listName.add(mContext.getString(R.string.card_credit));
				list.add(cardType);
			} else if (cardType.contains("DEBIT")) {
				listName.add(mContext.getString(R.string.card_debit));
				list.add(cardType);
			}
		}
		if (0 == list.size()) {
			HPLog.e(TAG, "No available application to select. cancel it");
			mSelectApplication.showNoAvailableApp(new Runnable() {
				@Override
				public void run() {
					if (null != wisePadController) {
						wisePadController.cancelSelectApplication();
					}
				}
			});
			return;
		}
		// prompt to select cardType
		final IICSelectApplicationCallback selectApplicationCallback = new IICSelectApplicationCallback() {
			public void onCardTypeSelect(int index) {
				HPLog.i(TAG, "list size:" + list.size() + " and user select " + index);
				if (null != wisePadController && -1 != index && index < list.size()) {
					int realIndex = findIndex(strings, list.get(index));
					if (-1 != realIndex && realIndex < strings.size()) {
						// 记录用户选择的ApplicationType
						mSwipeTransData.mICSelectedApplication = list.get(index);
						wisePadController.selectApplication(index);
					} else {
						HPLog.e(TAG, "cannot find this select: " + realIndex + ", so cancel it!");
						wisePadController.cancelSelectApplication();
					}
				} else {
					HPLog.e(TAG, "cancel select Application");
					wisePadController.cancelSelectApplication();
				}
			}
		};
		mSelectApplication.showSelectICApp(listName, selectApplicationCallback);
	}

	@Override
	public void onRequestSetAmount() {
		HPLog.i(TAG, "onRequestSetAmount:");
		CurrencyCharacter[] currencyCharacters = new CurrencyCharacter[] { CurrencyCharacter.YUAN };
		// 这个里面的值都是没有意义的。和我们业务无关。
		wisePadController.setAmount("1", "", "156", WisePadController.TransactionType.GOODS, currencyCharacters);
		/*
		 * "1", "", "156", TransactionType.GOODS);
		 */
	}

	@Override
	public void onRequestVerifyID(String s) {
		HPLog.i(TAG, "onRequestVerifyID:");
	}

	@Override
	public void onRequestCheckServerConnectivity() {
		HPLog.i(TAG, "onRequestCheckServerConnectivity:");
	}

	@Override
	public void onRequestOnlineProcess(String s) {
		HPLog.i(TAG, "onRequestOnlineProcess:" + s);
		mData = s;
		// 这里用于发送第一个。
		// wisePadController.viposExchangeApdu(apdus[0]); //
		// 这种方式M188命令不能响应。。。改为下面直接发sendOnlineProcessResult指令则交易结果
		wisePadController.sendOnlineProcessResult("8A023030");
		// mLock.unlock(AsynSwiperLock.OLD_INPUT_PWD);
	}

	@Override
	public void onRequestTerminalTime() {
		HPLog.i(TAG, "onRequestTerminalTime:");
		String time = new SimpleDateFormat("yyMMddHHmmss").format(Calendar.getInstance().getTime());
		wisePadController.sendTerminalTime(time);
	}

	@Override
	public void onRequestDisplayText(DisplayText displayText) {
		HPLog.i(TAG, "onRequestDisplayText:" + displayText);
	}

	@Override
	public void onRequestClearDisplay() {
		HPLog.i(TAG, "onRequestClearDisplay:");
	}

	@Override
	public void onRequestReferProcess(String s) {
		HPLog.i(TAG, "onRequestReferProcess:" + s);
	}

	@Override
	public void onRequestAdviceProcess(String s) {
		HPLog.i(TAG, "onRequestAdviceProcess:" + s);
	}

	@Override
	public void onRequestFinalConfirm() {
		HPLog.i(TAG, "onRequestFinalConfirm:");
		wisePadController.sendFinalConfirmResult(true);
	}

	@Override
	public void onBatteryLow(BatteryStatus batteryStatus) {
		HPLog.i(TAG, "onBatteryLow:" + batteryStatus);
		if (null != mSelectApplication && mSelectApplication instanceof SwiperCallback) {
			((SwiperCallback) mSelectApplication).onBatteryLow();
		}
	}

	@Override
	public void onDevicePlugged() {
		HPLog.i(TAG, "onDevicePlugged:");
	}

	@Override
	public void onDeviceUnplugged() {
		HPLog.i(TAG, "onDeviceUnplugged:");
		mLock.unlock(AsynSwiperLock.IDLE);
	}

	@Override
	protected boolean prepareAdditionalData() {
		boolean result = super.prepareAdditionalData();
		if (mSwipeTransData.isIcTrans) {
			HPLog.i(TAG, "ic trans. startEmv to get DCData");
			if (iccStartEmv().mStatus != SwipeStatus.SWIPE_OK) {
				return false;
			}
		}
		return result;
	}

	@Override
	public void onAudioDeviceNotFound() {
		HPLog.i(TAG, "onAudioDeviceNotFound");
	}

	@Override
	public void onRequestInsertCard() {
		HPLog.i(TAG, "onRequestInsertCard");
	}

	@Override
	public void onReturnAmount(Hashtable<String, String> arg0) {
		HPLog.i(TAG, "onReturnAmount....Hashtable<String, String>" + arg0);
	}

	@Override
	public void onReturnAmountConfirmResult(boolean arg0) {
		HPLog.i(TAG, "onReturnAmountConfirmResult.. boolean " + arg0);
		if (arg0 == true) {
			if (mCheckCardResult == CheckCardResult.MCR) {
				isSetAmount = arg0;
				Hashtable<String, Object> data = new Hashtable<String, Object>();
				data.put("pinEntryTimeout", mSwipeTransData.mTimeout);
				data.put("randomNumber", mSwipeTransData.mFactor);
				wisePadController.startPinEntry(data);
				HPLog.e(TAG, "startPinEntry--");
			}
		} else {
			wisePadController.cancelSetAmount();
			mLock.unlock(AsynSwiperLock.NEW_INPUT_PWD);
		}
	}

	@Override
	public void onReturnDisableInputAmountResult(boolean arg0) {
		HPLog.i(TAG, "onReturnDisableInputAmountResult..boolean " + arg0);
	}

	@Override
	public void onReturnEmvCardBalance(boolean arg0, String arg1) {
		HPLog.i(TAG, "onReturnEmvCardBalance...boolean " + arg0 + "String.." + arg1);
	}

	@Override
	public void onReturnEmvTransactionLog(String[] arg0) {
		HPLog.i(TAG, "onReturnEmvTransactionLog...String[]" + arg0);
	}

	@Override
	public void onReturnEnableInputAmountResult(boolean arg0) {
		HPLog.i(TAG, "onReturnEnableInputAmountResult..boolean" + arg0);
	}

	@Override
	public void onReturnMagStripeCardNumber(CheckCardResult arg0, String arg1) {
		HPLog.i(TAG, "onReturnMagStripeCardNumber..CheckCardResult" + arg0 + "String.." + arg1);
	}

	@Override
	public void onReturnPhoneNumber(PhoneEntryResult arg0, String arg1) {
		HPLog.i(TAG, "onReturnPhoneNumber..PhoneEntryResult" + arg0 + "String--" + arg1);
	}

	@Override
	public void onReturnPinEntryResult(PinEntryResult arg0, Hashtable<String, String> data) {
		if (data != null) {
			pinResult = arg0;
			HPLog.i(TAG, "onReturnPinEntryResult..PinEntryResult" + arg0);
			String epb = data.get("epb");
			String ksn = data.get("ksn");
			String randomNumber = data.get("randomNumber");
			String encWorkingKey = data.get("encWorkingKey");
			mHTData.put(BANK_PAN_KEY, epb);
			mHTData.put("ksn", ksn);
			// mLock.unlock(AsynSwiperLock.OLD_INPUT_PWD);
		}
		mLock.unlock(AsynSwiperLock.NEW_INPUT_PWD);
	}

	@Override
	public void onReturnReadTerminalSettingResult(TerminalSettingStatus arg0, String arg1) {
		HPLog.i(TAG, "onReturnReadTerminalSettingResult..TerminalSettingStatus" + arg0);
	}

	@Override
	public void onReturnUpdateTerminalSettingResult(TerminalSettingStatus arg0) {
		HPLog.i(TAG, "onReturnUpdateTerminalSettingResult..TerminalSettingStatus" + arg0);
	}

	// ------------------------------------------------
	private String mAmount;

	@Override
	public void onReturnEmvLoadLog(String[] arg0) {
		HPLog.i(TAG, "onReturnEmvLoadLog");
	}

	public final String BANK_ACCOUNT_KEY = "account";
	public final String BANK_PLAIN_ACCOUNT_KEY = "PlainAccountKey";
	public final String BANK_PAN_KEY = "pin";
	public final String BANK_AMOUNT_KEY = "amount";
	public final String BANK_TRACK2_KEY = "track2";
	public final String BANK_TRACK3_KEY = "track3";
	public final String BANK_DYNAMIC_KEY = "dynamicKeyData";
	public final String BANK_ICNUMBER = "icnumber";
	public final String BANK_DCDATA = "dcdata";
	// 新版 2.0.0
	public final String BANK_PLAIN_EXPIRE_DATE = "plainExpireDate";
	public static final int FLAG_NORMAL = 2;
	public static final int FLAG_SUPER = 1;

	/**
	 * 消费通知新增
	 */
	public final String BANK_TransactionType_KEY = "transationType";// 新增消费通知的标记
	public final String BANK_MerchantID_KEY = "merchantId";
	public final String BANK_TerminalID_KEY = "terminalId";
	public final String BANK_OrderID_KEY = "orderId";
	// 金额本来可以按照帅哥的那种方式显示在密码页面，但是为了不影响已经稳固的转账交易，还是先区分开来，修改起来也不难。
	public final String BANK_TransAmount_KEY = "transAmount";

	@Override
	public void onConnected(BluetoothDevice bluetoothDevice) {
		// 连接刷卡器回调
		wisePadController.getDeviceInfo();
		
	}

	@Override
	public void onDisconnected() {
		// 关闭连接刷卡器回调
		HPLog.i(TAG, "onBTv2Disconnected");
		mData = null;
		wisePadController = null;
		mContext = null;
		mSelectApplication = null;
		mSwipeTransData = null;
	}

	@Override
	public void onError(Error errorState, String errorMessage) {
		HPLog.i(TAG, "onError ...Error" + errorState);
		pinResult = PinEntryResult.CANCEL;
		mData = null;
		mCheckCardResult = null;
		if (mLock != null) {
			mLock.unlock(AsynSwiperLock.IDLE);
		}
	}

	@Override
	public void onPrintDataCancelled() {
		// 打印取消回调
	}

	@Override
	public void onPrintDataEnd() {
		// 停止打印操作
	}

	@Override
	public void onRequestPinEntry(PinEntrySource pinentrysource) {
		// 输入密码
		// 发送无意义的密码。真正的密码加密，后面再做。
		wisePadController.sendPinEntryResult("111111");

	}

	@Override
	public void onRequestPrintData(int arg0, boolean arg1) {
		// 打印数据
	}

	@Override
	public void onReturnApduResult(boolean arg0, String arg1, int arg2) {

	}

	@Override
	public void onReturnApduResultWithPkcs7Padding(boolean arg0, String arg1) {

	}

	@Override
	public void onReturnEncryptDataResult(boolean isSuccess, Hashtable<String, String> data) {
		// 加密数据
	}

	@Override
	public void onReturnEncryptPinResult(Hashtable<String, String> data) {
		// 加密密码
	}

	@Override
	public void onReturnInjectSessionKeyResult(boolean arg0, Hashtable<String, String> arg1) {

	}

	@Override
	public void onReturnPowerOffIccResult(boolean isSuccess) {
		Log.i(TAG, "onReturnPowerOffIccResult----" + isSuccess);
	}

	@Override
	public void onReturnPowerOnIccResult(boolean isSuccess, String ksn, String atr, int atrLength) {
		Log.i(TAG, "onReturnPowerOnIccResult----");
	}

	@Override
	public void onReturnPrintResult(PrintResult printResult) {
		Log.i(TAG, "onReturnPrintResult----" + printResult);
	}

	@Override
	public void onReturnScanResults(List<BluetoothDevice> foundDevices) {
		Log.i(TAG, "onReturnScanResults----" + foundDevices);
	}

	@Override
	public void onScanStopped() {
		// 停止搜索设备
		Log.i(TAG, "onScanStopped----");
	}

	@Override
	public void onScanTimeout() {
		// 搜索蓝牙超时
		Log.i(TAG, "onScanTimeout----");
	}

	@Override
	public void onWaitingReprintOrPrintNext() {
		// 请求重新打印
		Log.i(TAG, "onWaitingReprintOrPrintNext----");
	}
}
